using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace Atechnology.glassCAD.Shapes
{
    public class GlassItems60Invert : GlassItems60
    {

        public GlassItems60Invert(Param p) : base(p)
        {
            this.GetSizes();
        }

        internal override void GetSizes()
        {
            base.GetSizes();
            param.Width = this.GetRectangle().Width - B1;
            param.Height = this.GetRectangle().Height - B2;
            param.WidthFull = (float)Math.Round(this.GetRectangle().Width + this.GetHorizontalOffset()) + 1;
            param.HeightFull = (float)Math.Round(this.GetRectangle().Height + this.GetVerticalOffset()) + 1;
        }

        public override System.Drawing.RectangleF GetRectangle()
        {
            double width;
            double height;
            double rx;
            double ry;
            double G = Math.Sqrt(H * H + L * L);
            double R = (H1 * H1 + G * G / 4) / (2 * H1);
            double innerAngle;
            double startAngle;
            double endAngle;
            double E = G / 2;
            double psi = Math.Acos(E / R);
            double phi = Math.PI / 2 - psi;
            double beta;
            if (H1 < R)
            {
                beta = Math.Acos(H / G) - psi;
                innerAngle = 2 * phi;
            }
            else
            {
                innerAngle = 2 * (Math.PI - phi);
                beta = Math.Acos(H / G) + psi;
            }

            ry = H - R * Math.Cos(beta) + b2;

            double alpha = Math.PI / 2 - beta;

            double dRx = R * Math.Cos(alpha);
            
            if (ry <= 0)
            {
                width = b1 + L + b3;
                rx = b3 + L - dRx;
            }
            else
            {
                rx = b3 + R;
                width = R + b3 + dRx + b1;
                
            }
           
            if (rx > width)
                height = b2 + H + b3;
            else
                height = ry + R + b3;

            return new RectangleF((float)this.GetHorizontalOffset(), (float)this.GetVerticalOffset(), (float)(width - this.GetHorizontalOffset()), (float)(height - this.GetVerticalOffset()));                   
        }

        public override Shape GetInvert()
        {
            GlassItems60 result = new GlassItems60();
            result.H = this.H;
            result.L = this.L;
            result.H1 = this.H1;
            result.B1 = this.B1;
            result.B2 = this.B2;
            result.B3 = this.B3;
            return result;
        }

        public override double GetVerticalOffset()
        {
            return B3;
        }

        public override double GetHorizontalOffset()
        {
            return B3;
        }

        public override Atechnology.Spreading.Collections.colLine GetConturForSpreading()
        {

            Atechnology.Spreading.Collections.colLine resiult = new Atechnology.Spreading.Collections.colLine();

            Atechnology.Spreading.Classes.clsLine clsLine1 =
                new Atechnology.Spreading.Classes.clsLine(new Atechnology.Spreading.Classes.clsPoint(0, 0),
                                                          new Atechnology.Spreading.Classes.clsPoint(l, h),
                                                          h1,
                                                          Atechnology.Spreading.Orient.Right);
            resiult.Add(clsLine1);
            Atechnology.Spreading.Classes.clsLine clsLine2 = new Atechnology.Spreading.Classes.clsLine(l, 0, 0, 0);
            resiult.Add(clsLine2);
            Atechnology.Spreading.Classes.clsLine clsLine4 = new Atechnology.Spreading.Classes.clsLine(l, 0, l, h);
            resiult.Add(clsLine4);

            return resiult;
        }

        public override Atechnology.glassCAD.Shapes.Dxf.Dxf[] GetDxfContours()
        {
            if (this.isInverted)
            {
                return this.GetInvert().GetDxfContours();
            }

            double width;
            double height;
            double rx;
            double ry;
            double G = Math.Sqrt(H * H + L * L);
            double R = (H1 * H1 + G * G / 4) / (2 * H1);
            double innerAngle;
            double startAngle;
            double endAngle;
            double E = G / 2;
            double psi = Math.Acos(E / R);
            double phi = Math.PI / 2 - psi;
            double beta;
            if (H1 < R)
            {
                beta = Math.Acos(H / G) - psi;
                innerAngle = 2 * phi;
            }
            else
            {
                innerAngle = 2 * (Math.PI - phi);
                beta = Math.Acos(H / G) + psi;
            }

            double alpha = Math.PI / 2 - beta;

            ry = H - R * Math.Cos(beta) + b2;

            double dRx = R * Math.Cos(alpha);

            if (ry <= 0)
            {
                width = b1 + L + b3;
                rx = b3 + L - dRx;
            }
            else
            {
                rx = b3 + R;
                width = dRx + R + b3 + b1;
            }

            if (rx > width)
                height = b2 + H + b3;
            else
                height = ry + R + b3;

            startAngle = alpha;

            if (startAngle < 0) startAngle = 2 * Math.PI + startAngle;

            endAngle = alpha + innerAngle;

            Dxf.Dxf dxf = new Atechnology.glassCAD.Shapes.Dxf.Dxf();
            Dxf.Line line1 = new Atechnology.glassCAD.Shapes.Dxf.Line(new PointF((float)width - B1 - L, B2), new PointF((float)width - B1, B2));
            Dxf.Line line2 = new Atechnology.glassCAD.Shapes.Dxf.Line(new PointF((float)width - B1, B2),  new PointF((float)width - B1, B2 + H));
            Dxf.Arc arc1 = new Atechnology.glassCAD.Shapes.Dxf.Arc(new PointF((float)rx, (float)ry), (float)R, (float)(startAngle * 180 / Math.PI), (float)(endAngle * 180 / Math.PI));
            dxf.Add(line1);            
            dxf.Add(line2);
            dxf.Add(arc1);

            return new Atechnology.glassCAD.Shapes.Dxf.Dxf[] { dxf }; 
        }

        public override void DrawState(System.Drawing.Graphics graphics, Atechnology.glassCAD.Shapes.Dxf.DxfDrawer.State state, System.Drawing.Color fillColor)
        {
            if (this.isInverted)
            {
                this.GetInvert().DrawState(graphics, state, fillColor);
                return;
            }

            Dxf.Dxf dxf = new FilledDxf();
            float _width = this.GetRectangle().Width + (float)this.GetHorizontalOffset();
            float _height = this.GetRectangle().Height + (float)this.GetVerticalOffset();
            Dxf.Line _line1 = new Atechnology.glassCAD.Shapes.Dxf.Line(new PointF(0, 0), new PointF(_width, 0));
            Dxf.Line _line2 = new Atechnology.glassCAD.Shapes.Dxf.Line(new PointF(_width, 0), new PointF(_width, _height));
            Dxf.Line _line3 = new Atechnology.glassCAD.Shapes.Dxf.Line(new PointF(_width, _height), new PointF(0, _height));
            Dxf.Line _line4 = new Atechnology.glassCAD.Shapes.Dxf.Line(new PointF(0, _height), new PointF(0, 0));
            dxf.Add(_line1);
            dxf.Add(_line2);
            dxf.Add(_line3);
            dxf.Add(_line4);
            Dxf.DxfDrawer.Draw(graphics, dxf, state, fillColor);

            double width;
            double height;
            double rx;
            double ry;
            double G = Math.Sqrt(H * H + L * L);
            double R = (H1 * H1 + G * G / 4) / (2 * H1);
            double innerAngle;
            double startAngle;
            double endAngle;
            double E = G / 2;
            double psi = Math.Acos(E / R);
            double phi = Math.PI / 2 - psi;
            double beta;
            if (H1 < R)
            {
                beta = Math.Acos(H / G) - psi;
                innerAngle = 2 * phi;
            }
            else
            {
                innerAngle = 2 * (Math.PI - phi);
                beta = Math.Acos(H / G) + psi;
            }

            double alpha = Math.PI / 2 - beta;

            ry = H - R * Math.Cos(beta) + b2;

            double dRx = R * Math.Cos(alpha);

            if (ry <= 0)
            {
                width = b1 + L + b3;
                rx = b3 + L - dRx;
            }
            else
            {
                rx = b3 + R;
                width = dRx + R + b3 + b1;                
            }

            if (rx > width)
                height = b2 + H + b3;
            else
                height = ry + R + b3;

            startAngle = alpha;

            if (startAngle < 0) startAngle = 2 * Math.PI + startAngle;

            endAngle = alpha + innerAngle;

            dxf = new Atechnology.glassCAD.Shapes.Dxf.Dxf();
            Dxf.Line line1 = new Atechnology.glassCAD.Shapes.Dxf.Line(new PointF((float)width - B1, B2), new PointF((float)width - B1 - L, B2));
            Dxf.Line line2 = new Atechnology.glassCAD.Shapes.Dxf.Line(new PointF((float)width - B1, B2), new PointF((float)width - B1, B2 + H));
            Dxf.Arc arc1 = new Atechnology.glassCAD.Shapes.Dxf.Arc(new PointF((float)rx, (float)ry), (float)R, (float)(startAngle * 180 / Math.PI), (float)(endAngle * 180 / Math.PI));
            dxf.Add(line1);
            dxf.Add(line2);
            dxf.Add(arc1);
            Dxf.DxfDrawer.Draw(graphics, dxf, state, fillColor);
        }

        public override List<string> GetAnzData()
        {
            if (this.isInverted)
                return this.GetInvert().GetAnzData();

            double width;
            double height;
            double rx;
            double ry;
            double G = Math.Sqrt(H * H + L * L);
            double R = (H1 * H1 + G * G / 4) / (2 * H1);
            double innerAngle;
            double startAngle;
            double endAngle;
            double E = G / 2;
            double psi = Math.Acos(E / R);
            double phi = Math.PI / 2 - psi;
            double beta;
            if (H1 < R)
            {
                beta = Math.Acos(H / G) - psi;
                innerAngle = 2 * phi;
            }
            else
            {
                innerAngle = 2 * (Math.PI - phi);
                beta = Math.Acos(H / G) + psi;
            }

            double alpha = Math.PI / 2 - beta;

            ry = H - R * Math.Cos(beta) + b2;

            double dRx = R * Math.Cos(alpha);

            if (ry <= 0)
            {
                width = b1 + L + b3;
                rx = b3 + L - dRx;
            }
            else
            {
                rx = b3 + R;
                width = dRx + R + b3 + b1;

            }

            if (rx > width)
                height = b2 + H + b3;
            else
                height = ry + R + b3;

            startAngle = alpha;

            if (startAngle < 0) startAngle = 2 * Math.PI + startAngle;

            endAngle = alpha + innerAngle;

            double startX = width - B1;
            double startY = b2 + H;
            double endX = width - B1 - L;
            double endY = b2;


            List<string> anz = new List<string>();
            anz.Add((width).ToString("0.000000", culture) + " " + (height).ToString("0.000000", culture) + " " + "0");
            anz.Add("1 0 0 2");
            anz.Add("0.000000");
            anz.Add("0.000000");

            anz.Add("1 0 0 2");
            anz.Add((width).ToString("0.000000", culture));
            anz.Add((height).ToString("0.000000", culture));

            anz.Add("3 0 0 2");
            anz.Add((rx).ToString("0.000000", culture));
            anz.Add((ry).ToString("0.000000", culture));
            anz.Add(R.ToString("0.000000", culture));
            anz.Add(startAngle.ToString("0.000000", culture));
            anz.Add(endAngle.ToString("0.000000", culture));
            anz.Add((startX).ToString("0.000000", culture));
            anz.Add(startY.ToString("0.000000", culture));
            anz.Add(endX.ToString("0.000000", culture));
            anz.Add(endY.ToString("0.000000", culture));
            if (b1 != 0)
            {
                anz.Add("2 0 0 2");
                anz.Add((width - B1).ToString("0.000000", culture));
                anz.Add(b2.ToString("0.000000", culture));
                anz.Add((width - B1).ToString("0.000000", culture));
                anz.Add(height.ToString("0.000000", culture));
            }
            if (b2 != 0)
            {
                anz.Add("2 0 0 2");
                anz.Add(width.ToString("0.000000", culture));
                anz.Add(b2.ToString("0.000000", culture));
                anz.Add(0.ToString("0.000000", culture));
                anz.Add(b2.ToString("0.000000", culture));
            }
            anz.Add("7 0 0 7");
            anz.Add((width / 2).ToString("0.000000", culture));
            anz.Add((height / 2).ToString("0.000000", culture));

            return anz;

        }
    }
}
